<?php

namespace app\model;

use Laf\Log;
use mon\orm\Model;
use mon\util\Instance;
use mon\util\Container;
use mon\orm\exception\DbException;

/**
 * 角色组模型
 *
 * Class AuthGroup
 * @copyright 2021-03-24 mon-console
 * @version 1.0.0
 */
class AuthGroupModel extends Model
{
    use Instance;

    /**
     * 操作表
     *
     * @var string
     */
    protected $table = 'auth_group';

    /**
     * 新增自动写入字段
     *
     * @var array
     */
    protected $insert = ['create_time', 'update_time'];

    /**
     * 更新自动写入字段
     *
     * @var array
     */
    protected $update = ['update_time'];

    /**
     * 验证器
     *
     * @var string
     */
    protected $validate = \app\validate\Auth::class;

    /**
     * 权限控制类库模型
     *
     * @var \mon\auth\rbac\model\Group
     */
    protected $authGroupModel;

    /**
     * 构造方法
     */
    public function __construct()
    {
        $this->authGroupModel = Container::instance()->auth->model('group');
    }

    /**
     * 查询信息
     *
     * @param array $where
     * @param mixed $field
     * @return mixed
     */
    public function getInfo(array $where, $field = '*')
    {
        $info = $this->where($where)->field($field)->find();
        if (!$info) {
            $this->error = '角色组信息不存在';
            return false;
        }

        return $info;
    }

    /**
     * 新增角色组
     *
     * @param array $option 请求参数
     * @return boolean
     */
    public function add($option)
    {
        $check = $this->validate()->data($option)->scope('add_group')->check();
        if ($check !== true) {
            $this->error = $this->validate()->getError();
            return false;
        }

        $this->startTrans();
        try {
            $info = [
                'pid'       => $option['pid'],
                'title'     => $option['title'],
                'rules'     => [],
                'status'    => $option['status'],
            ];
            Log::instance()->oss(__FILE__, __LINE__, 'add admin group', 'sql');
            $save = $this->authGroupModel->add($info);
            if (!$save) {
                $this->rollback();
                $this->error = $this->authGroupModel->getError();
                return false;
            }

            // 记录操作日志
            $record = AdminLogModel::instance()->record(['action' => '新增角色组', 'content' => '新增角色组：' . $option['title']]);
            if (!$record) {
                $this->rollback();
                $this->error = '记录操作日志失败';
                return false;
            }

            $this->commit();
            return true;
        } catch (DbException $e) {
            $this->rollback();
            $this->error = '新增角色组异常';
            Log::instance()->oss(__FILE__, __LINE__, 'add admin group exception, msg => ' . $e->getMessage(), 'error');
            return false;
        }
    }

    /**
     * 编辑角色组
     *
     * @param array $option 请求参数
     * @return boolean
     */
    public function edit($option)
    {
        $check = $this->validate()->data($option)->scope('modify_group')->check();
        if ($check !== true) {
            $this->error = $this->validate()->getError();
            return false;
        }
        // 获取原数据
        $groupInfo = $this->authGroupModel->getInfo(['id' => $option['idx']]);
        if (!$groupInfo) {
            $this->error = $this->authGroupModel->getError();
            return false;
        }
        // 处理权限规则为数组
        $rules = explode(',', $option['rules']);
        foreach ($rules as $k => $item) {
            if (empty($item)) {
                unset($rules[$k]);
            }
        }
        $info = [
            'idx'       => $option['idx'],
            'pid'       => $option['pid'],
            'title'     => $option['title'],
            'rules'     => $rules,
            'status'    => $option['status'],
        ];

        $this->startTrans();
        try {
            Log::instance()->oss(__FILE__, __LINE__, 'edit admin group', 'sql');
            $save = $this->authGroupModel->modify($info);
            if (!$save) {
                $this->rollback();
                $this->error = $this->authGroupModel->getError();
                return false;
            }

            // 记录操作日志
            $record = AdminLogModel::instance()->record(['action' => '修改角色组', 'content' => json_encode($info, JSON_UNESCAPED_UNICODE)]);
            if (!$record) {
                $this->rollback();
                $this->error = '记录操作日志失败';
                return false;
            }

            $this->commit();
            return true;
        } catch (DbException $e) {
            $this->rollback();
            $this->error = '编辑角色组异常';
            Log::instance()->oss(__FILE__, __LINE__, 'edit admin group exception, msg => ' . $e->getMessage(), 'error');
            return false;
        }
    }

    /**
     * 获取树状组别数据
     *
     * @param boolean $parseList 是否转换格式
     * @return array
     */
    public function getGroupTree($parseList = false)
    {
        $groups = $this->field('id, pid, title, status')->select();
        foreach ($groups as &$item) {
            $item['spread'] = true;
        }
        if ($parseList) {
            $result = Container::instance()->tree->data($groups)->getTreeList(Container::instance()->tree->data($groups)->getTreeArray(0), 'title');
        } else {
            $result = Container::instance()->tree->data($groups)->getTree('children');
        }

        return $result;
    }

    /**
     * 获取用户组下所有权限
     *
     * @param integer $id   权限角色组ID
     * @param integer $pid  权限角色组父级ID
     * @return mixed
     */
    public function getRoleTree($id = 0, $pid = 0)
    {
        $userRule = [];
        // 存在自身ID，获取自身权限节点
        if ($id > 0) {
            $userGroup = $this->where('id', $id)->find();
            $userRule = explode(",", $userGroup['rules']);
        }

        // 获取规则列表
        $ruleListQuery = AuthRuleModel::instance()->field('id, pid, title');
        if ($pid > 0) {
            // 存在父级，获取父级所有权限规则
            $parentGroup = $this->where('id', $pid)->find();
            if (!$parentGroup) {
                $this->error = '获取父级组别信息失败';
                return false;
            }
            if (!in_array('*', explode(',', $parentGroup['rules']))) {
                $ruleListQuery->whereIn('id', $parentGroup['rules']);
            }
        }
        $ruleList = $ruleListQuery->select();
        // 重组节点数据
        $result = [];
        foreach ($ruleList as $k => $v) {
            $result[] = [
                'id'    => $v['id'],
                'parent' => ($v['pid'] == 0) ? '#' : $v['pid'],
                'state'    => [
                    'selected' => $this->getChecked($v['id'], $userRule, $ruleList)
                ],
                'text'    => $v['title'],
                'type'    => 'menu'
            ];
        }

        return $result;
    }

    /**
     * getRoleTree辅助方法，获取state的值
     *
     * @param  integer  $id         ID值
     * @param  array    $rules      用户规则
     * @param  array    $ruleList   规则列表
     * @return boolean
     */
    protected function getChecked($id, array $rules, array $ruleList)
    {
        // 超级管理员
        if (in_array("*", $rules)) {
            return true;
        }

        // 获取当前节点子节点，不为空则存在子集，false
        $rule = Container::instance()->tree->data($ruleList)->getChild($id);
        return (empty($rule) && in_array($id, $rules));
    }

    /**
     * 自动完成create_time字段
     * 
     * @param mixed $val 默认值
     * @param array  $row 列值
     * @return string
     */
    protected function setCreateTimeAttr($val)
    {
        return time();
    }

    /**
     * 自动完成update_time字段
     * 
     * @param mixed $val 默认值
     * @param array  $row 列值
     * @return string
     */
    protected function setUpdateTimeAttr($val)
    {
        return time();
    }
}
